<template>
  <ElSelect
    v-model="selectValue"
    :placeholder="placeholder"
    :disabled="disabled"
    :clearable="clearable"
    :filterable="filterable"
    :allow-create="allowCreate"
    :size="size || 'default'"
    :loading="loading"
    :multiple="multiple"
    :collapse-tags="collapseTags"
    :multiple-limit="multipleLimit"
    :name="name"
    :id="id"
    :validate-event="validateEvent"
    @change="handleChange"
    @clear="handleClear"
    @blur="handleBlur"
    @focus="handleFocus"
    @visible-change="handleVisibleChange"
    :style="selectStyle"
    class="dict-select"
  >
    <ElOption
      v-for="item in dictOptions"
      :key="item.value"
      :label="item.label"
      :value="item.value"
      :disabled="item.disabled"
    >
      <slot name="option" :item="item">{{ item.label }}</slot>
    </ElOption>
    <template #empty>
      {{ emptyText || '无匹配数据' }}
    </template>
  </ElSelect>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, watch } from 'vue'
import { ElSelect, ElOption } from 'element-plus'
import { useDict } from './useDict'

// Props定义
const props = defineProps<{
  /** 字典类型 */
  dictType: string
  /** 绑定值 */
  modelValue?: number | string | (number | string)[] | null
  /** 占位符 */
  placeholder?: string
  /** 是否禁用 */
  disabled?: boolean
  /** 是否可清空 */
  clearable?: boolean
  /** 是否可搜索 */
  filterable?: boolean
  /** 是否可创建 */
  allowCreate?: boolean
  /** 选择框大小 */
  size?: 'large' | 'default' | 'small'
  /** 是否多选 */
  multiple?: boolean
  /** 是否折叠多选标签 */
  collapseTags?: boolean
  /** 多选时用户最多可以选择的项目数 */
  multipleLimit?: number
  /** select的name属性 */
  name?: string
  /** select的id属性 */
  id?: string
  /** 是否触发表单验证 */
  validateEvent?: boolean
  /** 空状态文本 */
  emptyText?: string
  /** 自定义样式 */
  selectStyle?: Record<string, string>
}>()

// Emits定义
const emit = defineEmits<{
  (e: 'update:modelValue', value: number | string | (number | string)[] | null): void
  (e: 'change', value: number | string | (number | string)[]): void
  (e: 'clear'): void
  (e: 'blur', event: FocusEvent): void
  (e: 'focus', event: FocusEvent): void
  (e: 'visible-change', visible: boolean): void
  (e: 'dict-loaded', options: Array<{ label: string; value: number | string; disabled?: boolean }>): void
}>()

// 使用共享的 useDict 缓存
const { dictData, loading, loadDictData } = useDict(props.dictType)
const selectValue = ref<number | string | (number | string)[]>(props.modelValue || '')

// 计算属性：字典选项
const dictOptions = computed(() => {
  return dictData.value.map(item => ({
    label: item.dictLabel || '',
    value: item.dictValue || '',
    disabled: false // 可以根据需要从字典数据中获取disabled状态
  }))
})

// 保持对父组件的通知
watch(dictData, () => {
  emit('dict-loaded', dictOptions.value)
})

// 处理值变化
const handleChange = (value: number | string | (number | string)[]) => {
  selectValue.value = value
  emit('update:modelValue', value)
  emit('change', value)
}

// 处理清空
const handleClear = () => {
  selectValue.value = ''
  emit('update:modelValue', null)
  emit('clear')
}

// 处理失焦
const handleBlur = (event: FocusEvent) => {
  emit('blur', event)
}

// 处理聚焦
const handleFocus = (event: FocusEvent) => {
  emit('focus', event)
}

// 处理下拉框显示状态变化
const handleVisibleChange = (visible: boolean) => {
  emit('visible-change', visible)
}

// 监听字典类型变化
watch(() => props.dictType, (newType) => {
  if (newType) {
    loadDictData()
  }
})

// 监听外部modelValue变化
watch(() => props.modelValue, (newValue, oldValue) => {
  if (newValue === undefined || newValue === null) {
    selectValue.value = ''
  } else {
    selectValue.value = newValue
  }
}, { immediate: true, deep: true })

// 组件挂载时加载数据
onMounted(() => {
  if (props.dictType) {
    loadDictData()
  }
})

// 暴露方法供父组件调用
defineExpose({
  loadDictData,
  dictData,
  dictOptions,
  selectValue
})
</script>

<style scoped>
.dict-select {
  width: 100%;
}

:deep(.el-select__tags) {
  flex-wrap: wrap;
}
</style>